package pimpserver;

import java.io.*;
import java.math.BigInteger;
import java.net.*;
import java.security.KeyPair;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import netcom.*;

class ServerThread extends Thread
{
	private Socket client;
    private int ID;
    private Statistics stats;
    private Protocol protocol;
    private static final String SENDING_FILE = "SENDING_FILE";
    private static final String LOGIN = "LOGIN";
    private static final String OK = "OK";
    private static final String WRONG = "WRONG";
    private static final String GET_FILE = "GET_FILE";
    private boolean logged_in;
    private String user;

	ServerThread(Socket client,KeyPair keyPair, Statistics stats)
	{
        protocol = new Protocol(keyPair);
		this.client = client;
        ID = client.hashCode();
        this.stats = stats;
        logged_in = false;
        putInfo("Connection: " + client);
	}

    public void putInfo(String info)
    {
        System.out.println("\nID: " + ID + "\n" + info);
    }

	public void run()
	{
        putInfo("Starting thread");
        stats.addConnection();
		protocol.negotiateWithClient(client);
        String command = new String();
        String path = "";
        while(command.compareTo(protocol.getEndCode()) != 0)
        {
            command = protocol.getMsg();
            if(command.compareTo(protocol.getEndCode()) == 0)
                break;
            if(command == null)
                break;
            if(command.contains(LOGIN))
            {
                System.out.println("Logging in user");
                user = protocol.getMsg();
                path = "";
                try
                {
                    path = new java.io.File(".").getCanonicalPath();
                }
                catch (IOException ex)
                {
                    System.out.println("File I/O error: " + ex);
                }
                path = path + "\\" + user + "\\";
                File tmp = new File(path);
                tmp.mkdir();
                BufferedReader input = null;
                String good_pass = "";
                try
                {
                    input =  new BufferedReader(new FileReader(path + "pass.pass"));
                }
                catch (FileNotFoundException ex)
                {
                    System.out.println("File not found error: " + ex);
                }
                try
                {
                    good_pass = input.readLine();
                }
                catch (IOException ex)
                {
                    System.out.println("File empty, no such user ?");
                }
                String pass = protocol.getMsg();
                if(good_pass.compareTo(hashPassword(pass)) == 0)
                {
                    protocol.sendMsg(OK);
                    logged_in = true;
                }
                else
                {
                    protocol.sendMsg(WRONG);
                }
            }
            if(command.compareTo(SENDING_FILE) == 0)
            {
                System.out.println("User is sending a file");
                String file = new String(protocol.getMsg());
                if(logged_in)
                {
                    Writer output = null;
                    try
                    {
                        output = new BufferedWriter(new FileWriter(path + "data.xml"));
                    }
                    catch(IOException ex)
                    {
                        System.out.println("File error: " + ex);
                    }
                    try
                    {
                        output.write(file);
                    }
                    catch (IOException ex)
                    {
                        System.out.println("Could not write file: " + ex);
                    }
                    try
                    {
                        output.close();
                    }
                    catch (IOException ex)
                    {
                        System.out.println("Could not close file: " + ex);
                    }
                }
                else
                {
                    System.out.println("Not logged in");
                }
            }
            if(command.compareTo(GET_FILE) == 0)
            {
                System.out.println("User requested a file");
                if(logged_in)
                {
                    String file = "";
                    BufferedReader input = null;
                    try
                    {
                        input =  new BufferedReader(new FileReader(path + "data.xml"));
                    }
                    catch (FileNotFoundException ex)
                    {
                        System.out.println("File not found error: " + ex);
                    }
                    try
                    {
                        while(input.ready())
                        {
                            file = file + input.readLine() + "\n";
                        }
                    }
                    catch(IOException ex)
                    {
                        System.out.println("File I/O error");
                    }
                    protocol.sendMsg(file);
                }
                else
                {
                    System.out.println("Not logged in");
                }
            }
        }
        clean();
	}

    public static String hashPassword(String password)
    {
        String hashword = null;
        try
        {
            MessageDigest md5 = MessageDigest.getInstance("MD5");
            md5.update(password.getBytes());
            BigInteger hash = new BigInteger(1, md5.digest());
            hashword = hash.toString(16);
        }
        catch(NoSuchAlgorithmException nsae)
        {
            // ignore
        }
        return hashword;
    }
    
    protected void clean()
    {
        stats.removeConnection();
        try
		{
            putInfo("Closing connection");
			client.close();
		}
		catch(IOException e)
		{
			putInfo("Could not close client");
		}
    }
}
